﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace WeighClient.Utils
{
    public class WeightPortControlHelper
    {
        #region 字段/属性/委托
        /// <summary>  
        /// 串行端口对象  
        /// </summary>  
        private SerialPort sp;

        /// <summary>  
        /// 串口接收数据委托  
        /// </summary>  
        public delegate void ComReceiveDataHandler(string data);

        public ComReceiveDataHandler OnComReceiveDataHandler = null;

        /// <summary>  
        /// 端口名称数组  
        /// </summary>  
        public string[] PortNameArr { get; set; }

        /// <summary>  
        /// 串口通信开启状态  
        /// </summary>  
        public bool PortState { get; set; }

        /// <summary>  
        /// 编码类型  
        /// </summary>  
        public Encoding EncodingType { get; set; }
        #endregion

        private List<byte> buffer = new List<byte>(4096);
        public bool isOpen = false;
        #region 方法
        public WeightPortControlHelper()
        {
            PortState = false;
            EncodingType = Encoding.ASCII;
            PortNameArr = SerialPort.GetPortNames();
            sp = new SerialPort();
            sp.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
        }

        /// <summary>  
        /// 打开端口  
        /// </summary>  
        /// <param name="portName">端口名称</param>  
        /// <param name="boudRate">波特率</param>  
        /// <param name="dataBit">数据位</param>  
        /// <param name="stopBit">停止位</param>  
        /// <param name="timeout">超时时间</param>  
        public void OpenPort(string portName, int boudRate = 115200, int dataBit = 8, int stopBit = 1, int timeout = 5000)
        {
            try
            {
                sp.PortName = portName;
                sp.BaudRate = boudRate;
                sp.DataBits = dataBit;
                sp.StopBits = (StopBits)stopBit;
                sp.ReadTimeout = timeout;
                sp.Open();
                PortState = true;
                isOpen = true;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public bool IsOpen()
        {
            return isOpen;
        }
        /// <summary>  
        /// 关闭端口  
        /// </summary>  
        public void ClosePort()
        {
            try
            {
                sp.Close();
                PortState = false;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>  
        /// 接收数据回调用  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                int n = sp.BytesToRead;
                byte[] buf = new byte[n];
                sp.Read(buf, 0, n);

                //1.缓存数据
                this.buffer.AddRange(buf);
                //2.完整性判断
                while (this.buffer.Count >= 17) //至少包含帧头（2字节）、长度（1字节）、校验位（1字节）；
                {
                    if (this.buffer[0] == 0x02 && this.buffer[16] == 0x0D)
                    {
                        byte[] ReceiveBytes = new byte[17];
                        this.buffer.CopyTo(0,ReceiveBytes, 0,17);
                        this.buffer.RemoveRange(0, 17);

                        String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                        if (OnComReceiveDataHandler != null)
                        {
                            OnComReceiveDataHandler(hexString);
                        }
                    }
                    else
                    {
                        bool hasBeginChar = false;
                        for(int i=1; i<this.buffer.Count; i++)
                        {
                            if(this.buffer[i] == 0x02)
                            {
                                this.buffer.RemoveRange(0, i);
                                i = this.buffer.Count;
                                hasBeginChar = true;
                            }
                        }
                        if (!hasBeginChar)
                        {
                            this.buffer.RemoveRange(0, this.buffer.Count);
                        }
                    }
                }
            }
            catch (Exception ex) { }
        }
    }
}
#endregion